package org.sixtynine.stock.controller.front;

import java.util.Collections;
import java.util.List;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;

import org.sixtynine.stock.Constants;
import org.sixtynine.stock.Constants.ChartType;
import org.sixtynine.stock.ReturnData;
import org.sixtynine.stock.controller.AbstractFrontController;
import org.sixtynine.stock.criteria.StockSearchCriteria;
import org.sixtynine.stock.model.ColData;
import org.sixtynine.stock.model.GridData;
import org.sixtynine.stock.result.ShareResult;
import org.sixtynine.stock.result.Sortable;
import org.sixtynine.stock.result.StockResult;
import org.sixtynine.stock.service.StockManagerService;
import org.sixtynine.stock.util.SessionBean;
import org.sixtynine.stock.util.StockComparator;
import org.sixtynine.stock.util.StockComparator.ShareResultComparator;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.StringUtils;

/**
 * @author Thilanka
 * 
 */
public abstract class AbstractGridController extends AbstractFrontController {

	protected int pageSize = 10;

	@Autowired
	private StockManagerService service;

	public abstract ColData getColData();

	public ReturnData<List<ShareResult>> getGridData(
			StockSearchCriteria criteria, int page, Integer rows, String sidx,
			String sord, HttpSession session) {

		ReturnData<List<ShareResult>> output = new ReturnData<List<ShareResult>>();

		if (criteria == null) {
			criteria = new StockSearchCriteria();
		}
		List<ShareResult> results = null;
		if (rows != null && page > 1) {
			if (criteria.getChartType() != null && criteria.getChartType().equals(ChartType.BROAD_MARKET)) {
				results = (List<ShareResult>) session
						.getAttribute(Constants.BROAD_MARKET_RESULT);

			} else {
				results = (List<ShareResult>) session
						.getAttribute(Constants.SESSION_RESULTS);
			}
		}

		if (results == null) {
			ReturnData<List<ShareResult>> returnData = null;
			if (criteria.getChartType() != null
					&& criteria.getChartType().equals(ChartType.BROAD_MARKET)) {
				returnData = service.searchSectorCompanies(criteria);
			} else {
				returnData = service.search(criteria);
			}

			results = returnData.getData();
			if (criteria.getChartType() != null && criteria.getChartType().equals(ChartType.BROAD_MARKET)) {
				session.setAttribute(Constants.BROAD_MARKET_RESULT, results);
			} else {
				session.setAttribute(Constants.SESSION_RESULTS, results);

			}

		}

		if (!StringUtils.isEmpty(sidx) && !StringUtils.isEmpty(sord)) {
			Sortable sortable = new Sortable(sidx, sord);
			ShareResultComparator<ShareResult> comparator = (ShareResultComparator<ShareResult>) StockComparator
					.getInstance(StockComparator.SHARE_RESULT_COMPARATOR,
							sortable);
			comparator.setSortable(sortable);

			// add the asi as the first result always
			ShareResult asiResult = null;
			if (criteria._isAddAsiDetails()) {
				asiResult = results.remove(0);
			}
			Collections.sort(results, comparator);
			if (asiResult != null) {
				results.add(0, asiResult);
			}
		}

		int startIndex = (page - 1) * rows;
		int endIndex = startIndex + rows;

		if (results != null) {
			endIndex = endIndex > results.size() ? results.size() : endIndex;
			output.setData(results.subList(startIndex, endIndex));
			output.setNo(results.size());
		} else {
			output.setNo(0);
		}

		return output;
	}

	public GridData<ShareResult> getGridData(StockSearchCriteria criteria,
			int page, Integer rows, String sidx, String sord, String search,
			HttpServletRequest request) {
		GridData<ShareResult> gridData = new GridData<ShareResult>();

		SessionBean sBean = SessionBean.getInstance(request);
		if (search == null) {
			if (criteria==null && sBean.getAttr(Constants.SEARCH_CRITERIA) != null) {
				criteria = (StockSearchCriteria) sBean
						.getAttr(Constants.SEARCH_CRITERIA);
			}
		}

		// add the search criteria to session
		if (criteria != null) {
			sBean.setAttr(Constants.SEARCH_CRITERIA, criteria);
		} else {
			if (sBean.getAttr(Constants.SEARCH_CRITERIA) != null) {
				criteria = (StockSearchCriteria) sBean
						.getAttr(Constants.SEARCH_CRITERIA);
			}
		}

		HttpSession session = request.getSession();
		ReturnData<List<ShareResult>> data = getGridData(criteria, page, rows,
				sidx, sord, session);

		gridData.setData(data.getData());
		gridData.setPage(page);

		gridData.setTotal((data.getNo() / pageSize) + 1);
		gridData.setRecords(data.getNo());

		return gridData;
	}

	/**
	 * this is for sector data calculation
	 * 
	 * @param criteria
	 * @param page
	 * @param rows
	 * @param session
	 * @return
	 */
	public ReturnData<List<StockResult>> getGridSectorData(
			StockSearchCriteria criteria, int page, Integer rows,
			HttpSession session) {

		ReturnData<List<StockResult>> output = new ReturnData<List<StockResult>>();

		if (criteria == null) {
			criteria = new StockSearchCriteria();
		}
		List<StockResult> results = null;
		if (rows != null && page > 1) {
			results = (List<StockResult>) session
					.getAttribute(Constants.SESSION_RESULTS);
		}

		if (results == null) {
			ReturnData<List<StockResult>> returnData = service
					.searchSector(criteria);
			results = returnData.getData();
			session.setAttribute(Constants.SESSION_RESULTS, results);
		}

		int startIndex = (page - 1) * rows;
		int endIndex = startIndex + rows;
		endIndex = endIndex > results.size() ? results.size() : endIndex;
		output.setData(results.subList(startIndex, endIndex));
		output.setNo(results.size());

		return output;
	}

	/**
	 * this is for sector data calculation
	 * 
	 * @param criteria
	 * @param page
	 * @param rows
	 * @param request
	 * @return
	 */
	public GridData<StockResult> getGridSectorData(
			StockSearchCriteria criteria, int page, Integer rows,
			HttpServletRequest request) {
		GridData<StockResult> gridData = new GridData<StockResult>();

		HttpSession session = request.getSession();
		ReturnData<List<StockResult>> data = getGridSectorData(criteria, page,
				rows, session);

		gridData.setData(data.getData());
		gridData.setPage(page);

		gridData.setTotal(getPageSize());
		gridData.setRecords(data.getNo());

		return gridData;
	}

	public int getPageSize() {
		return pageSize;
	}

	protected boolean isUserLogged(HttpServletRequest request) {
		SessionBean sessionBean = SessionBean.getInstance(request);
		return (sessionBean.getUser() != null);
	}

}
